﻿using System;
using System.Collections.Generic;
using System.Text;
using MyGUI;
using MyGUI.Managed;
using ChaosEngine.GPU.Core;
using ChaosEngine.EngineCore.Graph;
using ChaosEngine.EngineCore.JS;
namespace ChaosEngine.EngineCore
{
    /// <summary>
    /// Central entry point for most forms of Chaos Applications. 
    /// 
    /// An CeApplication class should not be instantiated, instead you should extend it and add your custom functaility for your app. 
    /// This centralized methods allows you quick and easy access to many core components, and also facilitates faster execution.
    /// 
    /// see also:ceVideoSurface if you wish to embed a chaos engine display in your own custom app or window for a custom editor. This is primarly for creating
    /// 100% ChaosEditor compatible dll mods, which in turns can be turned into a runnable package to be distrubted to your end users.
    /// </summary>
    public class VividApp
    {
        /// <summary>
        /// Contains static(accessible anywhere) information regarding ChaosEngine's current application.
        /// </summary>
        public static class Info
        {

            /// <summary>
            /// The current framewidth. Can be altered by binding a render target or custom frame buffer.
            /// Updated automatically, never set this yourself.
            /// </summary>
            public static int FrameWidth = 0;
            /// <summary>
            /// The current framewidth. Can be altered by binding a render target or custom frame buffer.
            /// Updated automatically, never set this yourself.
            /// </summary>
            public static int FrameHeight = 0;
            /// <summary>
            /// Is true if the current app is running in windowed mode, if not possibly running fullscreen or embeded.
            /// </summary>
            public static bool FrameWindowed = false;

            public static string App = "";

        }

        public static class UI
        {
            public static MyGUI.Managed.Gui Gui;
            public static MyGUI.Managed.GuiFactory Factory;
        }

        public static class GPU
        {

            public static vGPUCore Core;
            public static Dictionary<string, vGPUCore> Map = new Dictionary<string, vGPUCore>();

        }

        /// <summary>
        /// You should access this when constructing your class that extends VividApp.
        /// 
        /// Like so,
        /// 
        /// public myConstructor(int w,int h,bool full,string title) : base(w,h,full,title)...
        /// </summary>
        /// <param name="fW">Desired framebuffer width</param>
        /// <param name="fH">Desired framebuffer height</param>
        /// <param name="fFS">If true, run in full screen mode, windowed otherwise.</param>
        /// <param name="fApp">Name of the app. very important to get this right. IS case-sensitive. It should match the name of your app subfolder within the filesys package/folder</param>
        public VividApp(int fW, int fH, bool fFS, string fApp, string api)
        {

            Info.FrameWidth = fW;
            Info.FrameHeight = fH;
            Info.FrameWindowed = fFS ? false : true;
            Info.App = fApp;

            CreateGPUPrototypes();

            GPU.Core = GetGPUCore(api).SpawnInstance();
        }
        public static class CurApp
        {

            public static VividApp App;
            public static string Path;
            public static bool IsTool;
            public static string FPath;
            public class UserApp
            {
                public static string FPath;
                public static ChaosEngine.EngineCore.JS.UserCode Code;
              
                public static dynamic Class;
            }
        }
        public static class JS
        {


        }
        public static class Vivid
        {

            public static dynamic Class;

        }

        public static class World
        {

            public static TransformGraph Visual;

        }

        public VividApp(string fApp, vGPUCore core, bool toolmode)
        {

            GPU.Core = core;
            CurApp.App = this;
            CurApp.Path = fApp;
            CurApp.IsTool = toolmode;
            var fApp2 = "drives-:app-A=" + fApp + "-";
            CurApp.FPath = FSHelper.AddrToPath(fApp2);
            Console.WriteLine("FPATH=:" + CurApp.FPath);
            var apath = "drives-:app-A=" + fApp + "->>classes->UserApp-";
            CurApp.UserApp.FPath = FSHelper.AddrToPath(apath);
            Console.WriteLine("APath=:" + CurApp.UserApp.FPath);

            CreateEngine();
            UserCode acore = new UserCode("drives-:engine->>classes->VividSystem-_class.cs");

            dynamic obj = acore.CreateClass("*");

            obj.InitVividSystem();

            Vivid.Class = obj;

            Factory.Node.FromLogic("VividSystemLogic", World.Visual.Root as TransformNode, obj);


            UserCode app = new UserCode(apath + "_class.cs");
            
            dynamic ac = app.CreateClass("*");
            CurApp.UserApp.Class = ac;
            TransformNode appNode = new TransformNode("AppCore", World.Visual.Root as TransformNode);
            appNode.AddLogic(ac);

            ac.InitApplication();


        }
        public void CreateEngine()
        {
            
            World.Visual = new TransformGraph("_GameVisual");
            NodeGraph.Current.SetCurrent(World.Visual);

        }
        
        
        public void RegisterGPUCore(vGPUCore core, string id)
        {
            GPU.Map.Add(
                id, core);

        }
        public vGPUCore GetGPUCore(string id)
        {
            return GPU.Map[id];
        }
        public bool CreateGPUPrototypes()
        {
            RegisterGPUCore(new ChaosEngine.GPU.API.DirectX.GCDX10(), "DX10");
            RegisterGPUCore(new ChaosEngine.GPU.API.DirectX.GCDX11(), "DX11");
            return true;
        }

        public virtual void UpdateApp() { }
        public virtual void DrawApp() { }
        public virtual void InitApp() { }


        public virtual int Run(float desired_fps)
        {
            GPU.Core.InitCore();
            GPU.Core.CreateForm(0, 0, Info.FrameWidth, Info.FrameHeight, Info.FrameWindowed ? false : true, Info.App);
            return GPU.Core.RunCore(this);

        }

    }
}
